package com.only4play.practice.asset.core.domainservice;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.only4play.codegen.support.base.EntityOperations;
import com.only4play.codegen.support.constants.ValidStatus;
import com.only4play.codegen.support.exception.BusinessException;
import com.only4play.practice.asset.core.domainservice.model.AssetBizInfo;
import com.only4play.practice.asset.core.domainservice.model.BatchInOutModel;
import com.only4play.practice.asset.core.domainservice.model.TransferModel;
import com.only4play.practice.asset.core.entity.Asset;
import com.only4play.practice.asset.core.envents.AssetEvents;
import com.only4play.practice.asset.core.mapper.AssetMapper;
import com.only4play.practice.asset.entitymapper.AssetObjectMapper;
import com.only4play.practice.asset.model.creator.AssetCreator;
import com.only4play.practice.common.enums.asset.AssetErrorCode;
import com.only4play.practice.common.enums.asset.InOutBizType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

@Service
@RequiredArgsConstructor
@Slf4j
public class AssetDomainServiceImpl implements IAssetDomainService {

    private final AssetMapper assetMapper;


    private final ApplicationEventPublisher publisher;
    @Override
    @Transactional
    public void handleAssetIn(BatchInOutModel batchInOutModel) {
        Assert.notEmpty(batchInOutModel.getUniqueCodes());
        String genBatchNo = IdUtil.simpleUUID();
        AssetBizInfo bizInfo = AssetBizInfo
                .builder()
                .batchNo(batchInOutModel.getBatchNo())
                .genBatchNo(genBatchNo)
                .inOutBizType(batchInOutModel.getInOutBizType())
                .uniqueCodes(batchInOutModel.getUniqueCodes())
                .operateUser(batchInOutModel.getOperateUser())
                .build();
        batchInOutModel.getUniqueCodes()
                .stream()
                .forEach(code -> {
                    QueryWrapper<Asset> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("house_id", batchInOutModel.getHouseId());
                    queryWrapper.eq("unique_code", code);
                    queryWrapper.eq("sku_id", batchInOutModel.getSkuId());
                    queryWrapper.last("limit 1");
                    Asset old = assetMapper.selectOne(queryWrapper);
                    if (ObjectUtil.isNotNull(old)){
                        // 如果已经存在则更新入库
                        EntityOperations
                                .doUpdate(assetMapper)
                                .load(() -> old)
                                .update(asset -> this.in(asset,bizInfo))
                                .execute();
                    }

                    if (!ObjectUtil.isNotNull(old)) {
                        // 不存在则直接入库
                        AssetCreator creator = new AssetCreator();
                        creator.setHouseId(batchInOutModel.getHouseId());
                        creator.setName(batchInOutModel.getName());
                        creator.setSkuId(batchInOutModel.getSkuId());
                        creator.setUniqueCode(code);
                        EntityOperations
                                .doCreate(assetMapper)
                                .create(() -> AssetObjectMapper.INSTANCE.dtoToEntity(creator))
                                .update(asset -> this.in(asset,bizInfo))
                                .execute();
                    }
                });
    }

    @Override
    @Transactional
    public void handleAssetOut(BatchInOutModel batchInOutModel) {
        Assert.notEmpty(batchInOutModel.getUniqueCodes());
        String genBatchNo = IdUtil.simpleUUID();
        AssetBizInfo bizInfo = AssetBizInfo
                .builder()
                .batchNo(batchInOutModel.getBatchNo())
                .genBatchNo(genBatchNo)
                .inOutBizType(batchInOutModel.getInOutBizType())
                .uniqueCodes(batchInOutModel.getUniqueCodes())
                .operateUser(batchInOutModel.getOperateUser())
                .build();
        batchInOutModel.getUniqueCodes()
                .stream()
                .forEach(code -> {
                    QueryWrapper<Asset> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("house_id", batchInOutModel.getHouseId());
                    queryWrapper.eq("unique_code", code);
                    queryWrapper.eq("sku_id", batchInOutModel.getSkuId());
                    queryWrapper.last("limit 1");
                    Asset old = assetMapper.selectOne(queryWrapper);

                    if(!ObjectUtil.isNotNull(old)){
                        throw new BusinessException(AssetErrorCode.ASSET_CODE_NOT_EXIST,"资产编码:"+code);
                    }else {
                        EntityOperations
                            .doUpdate(assetMapper)
                            .load(() -> old)
                            .update(asset -> this.out(asset,bizInfo))
                            .execute();
                    }
                });
    }

    @Override
    @Transactional
    public void handleAssetTransfer(TransferModel transferModel) {
        Assert.notEmpty(transferModel.getUniqueCodes());
        String genBatchNo = IdUtil.simpleUUID();
        BatchInOutModel outModel = new BatchInOutModel();
        outModel.setBatchNo(transferModel.getBatchNo());
        outModel.setInOutBizType(InOutBizType.OUT_TRANSFER);
        outModel.setOperateUser(transferModel.getOperateUser());
        outModel.setHouseId(transferModel.getTransferOutHouseId());
        outModel.setUniqueCodes(transferModel.getUniqueCodes());
        handleAssetOut(outModel);
        log.info("处理出库完成，仓库id:{},批次号:{},自动批号:{}", transferModel.getTransferOutHouseId(),transferModel.getBatchNo(),genBatchNo);
        // Optional<Asset> one = assetRepository.findOne(new BooleanBuilder()
        // .and(QAsset.asset.uniqueCode.eq(transferModel.getUniqueCodes().get(0))));
        QueryWrapper<Asset> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("unique_code", transferModel.getUniqueCodes().get(0));
        queryWrapper.last("limit 1");
        Asset one = assetMapper.selectOne(queryWrapper);
        BatchInOutModel inModel = new BatchInOutModel();
        inModel.setUniqueCodes(transferModel.getUniqueCodes());
        inModel.setName(one.getName());
        inModel.setInOutBizType(InOutBizType.IN_TRANSFER);
        inModel.setSkuId(transferModel.getSkuId());
        inModel.setOperateUser(transferModel.getOperateUser());
        inModel.setBatchNo(transferModel.getBatchNo());
        handleAssetIn(inModel);
        log.info("处理入库完成，仓库id:{},批次号:{},自动批号:{}", transferModel.getTransferOutHouseId(),transferModel.getBatchNo(),genBatchNo);

    }


    /**
     * 入库
     */
    public void in(Asset asset, AssetBizInfo bizInfo){
        if(Objects.equals(ValidStatus.VALID,asset.getValidStatus())){
            throw new BusinessException(AssetErrorCode.ASSET_HAS_IN);
        }
        asset.setValidStatus(ValidStatus.VALID);
        AssetEvents.AssetInEvent assetInEvent = new AssetEvents.AssetInEvent(asset, bizInfo);
        publisher.publishEvent(assetInEvent);
    }

    /**
     * 出库
     */
    public void out(Asset asset,AssetBizInfo bizInfo){
        if(Objects.equals(ValidStatus.INVALID,asset.getValidStatus())){
            throw new BusinessException(AssetErrorCode.ASSET_HAS_OUT);
        }
        asset.setValidStatus(ValidStatus.INVALID);
        publisher.publishEvent(new AssetEvents.AssetOutEvent(asset, bizInfo));

    }
}
